package cn.newhopedairy.common.handler;

import cn.newhopedairy.common.exception.ServiceException;
import cn.newhopedairy.common.wrapper.R;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletRequest;

/**
 * 自定义异常处理类
 *
 * 注：该Bean类位于common包，其他工程要引用并初始化该bean时，应新增扫描该包路径；
 * 例如：@SpringBootApplication(scanBasePackages = {"cn.newhopedairy.common.handler"})
 *
 * @author Neo.Li
 * @date 2020-09-09 17:59
 */
@RestControllerAdvice
public class ServiceExceptionHandler {
    /**
     * 表单提交时，请求参数绑定异常处理，在@Valid @Validated处
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(BindException.class)
    public R<Object> handleBindException(BindException exception) {
        return R.create(400, "请求参数绑定异常！", exception.getFieldErrors());
    }

    /**
     * json格式提交时，请求参数校验异常处理，在@Valid @Validated处
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException exception) {
        return R.create(400, "请求参数校验异常！", exception.getMessage());
    }

    /**
     * 请求参数类型错误处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R<Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException exception) {
        return R.create(400, "请求参数类型错误！", exception.getMessage());
    }

    /**
     * 请求参数缺失，空指针异常处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    public R<Object> handleNullPointerException(NullPointerException exception) {
        return R.create(500, "请求参数缺失，空指针异常！", exception.getStackTrace()[0]);
    }

    /**
     * 请求参数类型匹配错误处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public R<Object> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException exception) {
        return R.create(500, "请求参数类型匹配错误！", exception.getMessage());
    }

    /**
     * 请求参数类型转换错误处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(HttpMessageConversionException.class)
    public R<Object> handleHttpMessageConversionException(HttpMessageConversionException exception) {
        return R.create(500, "请求参数类型转换错误！", exception.getMessage());
    }

    /**
     * 业务异常处理
     *
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(ServiceException.class)
    public R<Object> handleBusinessException(HttpServletRequest request, ServiceException exception) {
        return R.create(exception.getStatusCode(), exception.getMessage());
    }
}
